home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / mdipad.zip / TOOLBAR.C < prev    next >
C/C++ Source or Header  |  1993-02-24  |  36KB  |  1,122 lines

  1. // ************************************************************************
  2. // MODULE    : ToolBar.C
  3. // PURPOSE   :
  4. // FUNCTIONS :
  5. // ************************************************************************
  6. #define NOCREATEFONT
  7.  
  8. #ifdef DEBUG
  9.   #define DebugOut( str ) OutputDebugString ( (LPCTSTR) __FILE__ TEXT( ": " ) TEXT( str ) TEXT( "\n" ) )
  10. #else
  11.   #define DebugOut( str )
  12. #endif
  13.  
  14. #ifndef WIN32
  15.  #define INT int
  16. #endif
  17.  
  18. #ifndef WIN32S
  19.  #define   UNICODE             // make the application unicode complient
  20. #endif
  21. #define   STRICT
  22. #include <windows.h>
  23.  
  24. #include <stdlib.h> // For 'abs'
  25.  
  26. #ifdef WIN32
  27.  #define GetWindowInstance(hwnd)  (HANDLE) GetWindowLong( hwnd, GWL_HINSTANCE )
  28.  #define GetWindowID(hwnd) GetWindowLong( hwnd, GWL_ID )
  29. #else
  30.  #define GetWindowInstance(hwnd)  (HANDLE) GetWindowWord( hwnd, GWW_HINSTANCE )
  31.  #define GetWindowID(hwnd) GetWindowWord( hwnd, GWW_ID )
  32. #endif
  33.  
  34. HWND    hwndMain;
  35. HWND    hwndTools, hwndToolText, hwndToolCombo, hwndToolButton;
  36. HWND    hwndStatus;
  37.  
  38. HFONT   hfontTools=0;
  39. HFONT   hfontStatus;
  40.  
  41. TEXTMETRIC tmToolFont;
  42. TEXTMETRIC tmStatusFont;
  43.  
  44. INT     dyTools = 0, dyCombo;
  45. INT     cxToolBorder, cyToolBorder, cntToolCtrls = 0;
  46. INT     xCurrent = 10;
  47. INT     dxTools;
  48.  
  49. INT     cntStatusField = 0;
  50. INT     dyStatus, cxStatusBorder, cyStatusBorder, cxFrame, cyFrame, dyField;
  51.  
  52. HBRUSH  hbrBtnFace=0;
  53. HBRUSH  hbrToolBar=0;
  54. HBRUSH  hbrStatus=0;
  55.  
  56. // HANDLE  hInst=0;
  57.  
  58. #define COLOR_BLACK     RGB(0, 0, 0)
  59. #define COLOR_WHITE     RGB(255, 255, 255)
  60. #define COLOR_HEAVYGRAY RGB(64, 64, 64)
  61. #define COLOR_DARKGRAY  RGB(128, 128, 128)
  62. #define COLOR_GRAY      RGB(192, 192, 192)
  63.  
  64. COLORREF rgbFrame       = COLOR_BLACK;
  65. COLORREF rgbBtnFace     = COLOR_GRAY;
  66. COLORREF rgbHilite      = COLOR_WHITE;
  67. COLORREF rgbDirectLight = COLOR_WHITE;
  68. COLORREF rgbShadow      = COLOR_DARKGRAY;
  69. COLORREF rgbToolBar     = COLOR_GRAY;
  70. COLORREF rgbStatic      = COLOR_BLACK;
  71.  
  72. #define TC_SPACE 0
  73. #define TC_LABEL 1
  74. #define TC_COMBO 2
  75. #define TC_BUTTON 3
  76.  
  77. #define MAXCTRLS 25
  78. typedef struct _tagTools {
  79.   HWND    hwnd;
  80.   WORD    wType;
  81.   INT     iWidth, iHeight;
  82.   HICON   hIcon;
  83. } Tools;
  84. Tools  toolCtrl[MAXCTRLS];
  85.  
  86. #define MAXSTATUS 10
  87. typedef struct _tagStatus {
  88.         HWND    hwnd;
  89.         INT     iMaxWidth, iMinWidth, iGiveWidth;
  90. } Status;
  91. Status  statusField[ MAXSTATUS ];
  92.  
  93. //-- internal prototypes
  94. LONG CALLBACK ToolsProc       (HWND, UINT, WPARAM, LPARAM);
  95. LONG CALLBACK MyComboProc     (HWND, UINT, WPARAM, LPARAM);
  96. VOID UpdatePositions (HWND);
  97.  
  98. LONG CALLBACK StatusProc      (HWND, UINT, WPARAM, LPARAM);
  99. LONG CALLBACK StatusFieldProc (HWND, UINT, WPARAM, LPARAM);
  100.  
  101. // ************************************************************************
  102. // FUNCTION : DllEntryPoint( HINSTANCE, DWORD, LPVOID )
  103. // PURPOSE  : DllEntryPoint is called by Windows when
  104. //            the DLL is initialized, Thread Attached, and other times.
  105. // COMMENTS : No initialization is needed here.
  106. // ************************************************************************
  107. BOOL WINAPI
  108. DllEntryPoint( HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved )
  109. {
  110.   UNREFERENCED_PARAMETER( hInstDLL );
  111.   UNREFERENCED_PARAMETER( fdwReason );
  112.   UNREFERENCED_PARAMETER( lpvReserved );
  113.  
  114.   return( TRUE );
  115. }
  116.  
  117. // ========================================================================
  118. //                        TOOL BAR FUNCTIONS
  119. // ========================================================================
  120.  
  121.  
  122. // ************************************************************************
  123. // FUNCTION : InitToolBar (HANDLE hInstance)
  124. // PURPOSE  :
  125. // COMMENTS :
  126. // ************************************************************************
  127. BOOL
  128. InitToolBar (HANDLE hInstance)
  129. {
  130.   WNDCLASS    wndclass;
  131.  
  132.   hbrBtnFace = CreateSolidBrush( rgbBtnFace );
  133.   hbrToolBar = CreateSolidBrush( rgbToolBar );
  134.  
  135.   wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  136.   wndclass.lpfnWndProc   = (WNDPROC) ToolsProc;
  137.   wndclass.cbClsExtra    = 0;
  138.   wndclass.cbWndExtra    = 0;
  139.   wndclass.hInstance     = hInstance;
  140.   wndclass.hIcon         = NULL;
  141.   wndclass.hbrBackground = hbrToolBar;
  142.   wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
  143.   wndclass.lpszMenuName  = NULL;
  144.   wndclass.lpszClassName = TEXT( "ToolBar" );
  145.  
  146.   if( !RegisterClass(&wndclass) )
  147.     return FALSE;
  148. }
  149.  
  150.  
  151. // ************************************************************************
  152. // FUNCTION : CreateToolBar( HWND hwnd, HANDLE hInstance, INT iId )
  153. // PURPOSE  :
  154. // COMMENTS :
  155. // ************************************************************************
  156. BOOL
  157. CreateToolBar( HWND hwnd, HANDLE hInstance, INT iId )
  158. {
  159.   HWND hwndTmp;
  160.   RECT rect;
  161.  
  162.   DebugOut( "CreateToolBar" );
  163.   if( hbrBtnFace==0 )
  164.     hbrBtnFace = CreateSolidBrush( rgbBtnFace );
  165.   if( hbrToolBar==0 )
  166.     hbrToolBar = CreateSolidBrush( rgbToolBar );
  167.   cxToolBorder = GetSystemMetrics( SM_CXBORDER );
  168.   cyToolBorder = GetSystemMetrics( SM_CYBORDER );
  169.   DebugOut( "Calling CreateWindow" );
  170.   hwndTools = CreateWindow ( TEXT( "ToolBar" ), TEXT( "ToolBar" ),
  171.                 WS_CHILD | WS_CLIPSIBLINGS | WS_BORDER | WS_VISIBLE,
  172.                 0, 0, 0, 0,
  173.                 hwnd, (HMENU) iId, hInstance, NULL );
  174.   if( !hwndTools ) {
  175.     DebugOut( "CreateWindow Failed" );
  176.     return FALSE;
  177.   }
  178.   DebugOut( "CreateWindow suceeded" );
  179.  
  180.   /* Lets find out how big a combo box is... */
  181.   hwndTmp = CreateWindow ( TEXT( "COMBOBOX" ), TEXT( "Combo" ),
  182.               WS_CHILD //| WS_CLIPSIBLINGS
  183.               | WS_VISIBLE | CBS_DROPDOWNLIST,
  184.                       0, 0, 0, 0,
  185.               hwndTools, NULL, hInstance, NULL);
  186.   if( hwndTmp ) {
  187.     // SendMessage( hwndTmp, WM_SETFONT, (UINT) hfontTools, MAKELONG (TRUE, 0) );
  188.     GetClientRect( hwndTmp, &rect );
  189.     dyCombo = rect.bottom - rect.top;
  190.     DestroyWindow( hwndTmp );
  191.   }
  192.   else {
  193.     dyCombo = 30; // Just for a default value
  194.   }
  195.  
  196.   hwndMain = hwnd; // So we can pass WM_CONTROL messages back to the master parent
  197.   hInstance; // unreferenced
  198.  
  199.   return TRUE;
  200. }
  201.  
  202.  
  203. // ************************************************************************
  204. // FUNCTION : ToolBarHeight( HWND hwnd )
  205. // PURPOSE  :
  206. // COMMENTS :
  207. // ************************************************************************
  208. int
  209. ToolBarHeight( HWND hwnd )
  210. {
  211.   RECT rect;
  212.  
  213.   GetClientRect( hwndTools, &rect );
  214.  
  215.   return( rect.bottom-rect.top );
  216.  
  217.   hwnd; // unreferenced
  218. }
  219.  
  220.  
  221. // ************************************************************************
  222. // FUNCTION : AdjustToolBar( HWND hwnd )
  223. // PURPOSE  :
  224. // COMMENTS :
  225. // ************************************************************************
  226. BOOL
  227. AdjustToolBar( HWND hwnd )
  228. {
  229.   RECT rect;
  230.  
  231.   GetClientRect (hwnd, &rect);
  232.   MoveWindow( hwndTools,
  233.     rect.left - cxToolBorder,
  234.     rect.top - cyToolBorder,
  235.     rect.right - rect.left + (cxToolBorder*2),
  236.     dyTools,
  237.     TRUE );
  238.  
  239.   return TRUE;
  240. }
  241.  
  242.  
  243. // ************************************************************************
  244. // FUNCTION : UpdatePositions( HWND hwnd )
  245. // PURPOSE  :
  246. // COMMENTS :
  247. // ************************************************************************
  248. VOID
  249. UpdatePositions( HWND hwnd )
  250. {
  251.   INT i, x, y, dx, dy, cnt;
  252.  
  253.   x = 10;
  254.   for( i=0; i<cntToolCtrls; i++ ) {
  255.  
  256.    switch( toolCtrl[i].wType ) {
  257.  
  258.      case TC_SPACE:
  259.        dx = toolCtrl[i].iWidth;
  260.        break;
  261.  
  262.      case TC_LABEL:
  263.        dy = toolCtrl[i].iHeight;
  264.        y = (dyTools/2) - (dy/2) - 1;
  265.        dx = toolCtrl[i].iWidth;
  266.        break;
  267.  
  268.      case TC_COMBO:
  269.        dy = toolCtrl[i].iHeight;
  270.        y = (dyTools/2) - (dy/2) - 1;
  271.        dx = toolCtrl[i].iWidth;
  272.        cnt = (INT) SendMessage( toolCtrl[i].hwnd, CB_GETCOUNT,
  273.                      (WPARAM) 0, (LPARAM) 0 );
  274.        if( cnt > 5 )
  275.          cnt = 5;
  276.        dy = dy * cnt;
  277.        break;
  278.  
  279.      case TC_BUTTON:
  280.        dy = toolCtrl[i].iHeight;
  281.        y = (dyTools/2) - (dy/2) - 1;
  282.        dx = toolCtrl[i].iWidth;
  283.        break;
  284.  
  285.      default:
  286.        dy = toolCtrl[i].iHeight;
  287.        y = (dyTools/2) - (dy/2) - 1;
  288.        dx = toolCtrl[i].iWidth;
  289.        break;
  290.  
  291.     }
  292.  
  293.     if( toolCtrl[i].wType != TC_SPACE ) {
  294.       MoveWindow( toolCtrl[i].hwnd, x, y, dx, dy, FALSE );
  295.     }
  296.     x += dx;
  297.   }
  298.  
  299.   if( hwnd == NULL ) {
  300.     UpdateWindow( hwndTools );
  301.   }
  302.   else{
  303.     UpdateWindow( hwnd );
  304.   }
  305. }
  306.  
  307. // ************************************************************************
  308. // FUNCTION : AddToolSpace( INT iWidth, INT iHeight )
  309. // PURPOSE  :
  310. // COMMENTS :
  311. // ************************************************************************
  312. BOOL
  313. AddToolSpace( INT iWidth, INT iHeight )
  314. {
  315.   if( cntToolCtrls >= MAXCTRLS )
  316.     return FALSE;
  317.   toolCtrl[cntToolCtrls].hwnd    = 0;
  318.   toolCtrl[cntToolCtrls].wType   = TC_SPACE;
  319.   toolCtrl[cntToolCtrls].iWidth  = iWidth;
  320.   toolCtrl[cntToolCtrls].iHeight = iHeight;
  321.  
  322.   if( (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder)) > dyTools ) {
  323.     dyTools = (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder));
  324.   }
  325.   UpdatePositions( NULL );
  326.   cntToolCtrls++;
  327.  
  328.   return( TRUE );
  329. }
  330.  
  331. // ************************************************************************
  332. // FUNCTION : AddToolLabel( HANDLE hInst, INT iId, LPTSTR szLabel, INT iWidth, DWORD dwStyle )
  333. // PURPOSE  :
  334. // COMMENTS :
  335. // ************************************************************************
  336. HWND
  337. AddToolLabel( HANDLE hInstance, INT iId, LPTSTR szLabel, INT iWidth, DWORD dwStyle )
  338. {
  339.   HDC hdc;
  340.  
  341.   if( cntToolCtrls >= MAXCTRLS )
  342.     return( (HWND) 0 ); // No room left in our fixed array
  343.  
  344.   toolCtrl[cntToolCtrls].hwnd = CreateWindow ( TEXT( "STATIC" ), szLabel,
  345.                                   WS_CHILD //| WS_CLIPSIBLINGS
  346.                                   | WS_VISIBLE | dwStyle,
  347.                                   0, 0, 0, 0,
  348.                                   hwndTools, (HMENU)iId, hInstance, NULL );
  349.  
  350.   if( !toolCtrl[cntToolCtrls].hwnd )
  351.     return( (HWND) 0 ); // CreateWindow failed for some reason
  352.  
  353.   // SendMessage (toolCtrl[cntToolCtrls].hwnd, WM_SETFONT, (UINT) hfontTools, MAKELONG (TRUE, 0) );
  354.   toolCtrl[cntToolCtrls].wType = TC_LABEL;
  355.  
  356.   hdc = GetDC (hwndTools);
  357.   if( iWidth < 0 ) {
  358.     toolCtrl[cntToolCtrls].iWidth = tmToolFont.tmAveCharWidth * abs(iWidth);
  359.   }
  360.   else if( iWidth == 0 ) {
  361. #ifdef WIN32
  362.     SIZE size;
  363.     GetTextExtentPoint( hdc, szLabel, lstrlen(szLabel), &size );
  364.     toolCtrl[cntToolCtrls].iWidth = size.cx;
  365. #else
  366.     toolCtrl[cntToolCtrls].iWidth = LOWORD( GetTextExtent( hdc, szLabel, lstrlen(szLabel) ) );
  367. #endif
  368.   }
  369.   else {
  370.     toolCtrl[cntToolCtrls].iWidth = iWidth;
  371.   }
  372.  
  373.   toolCtrl[cntToolCtrls].iHeight = tmToolFont.tmHeight;
  374.   if( (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder)) > dyTools ) {
  375.     dyTools = (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder));
  376.   }
  377.   ReleaseDC( hwndTools, hdc );
  378.   UpdatePositions( NULL );
  379.  
  380.   return( toolCtrl[cntToolCtrls++].hwnd );
  381. }
  382.  
  383.  
  384. // ************************************************************************
  385. // FUNCTION : AddToolCombo (HANDLE hInst, INT iId, INT iWidth, DWORD dwStyle)
  386. // PURPOSE  :
  387. // COMMENTS :
  388. // ************************************************************************
  389. HWND
  390. AddToolCombo (HANDLE hInstance, INT iId, INT iWidth, DWORD dwStyle)
  391. {
  392.  
  393.   if( cntToolCtrls >= MAXCTRLS )
  394.     return( (HWND) 0 ); // No room left in our fixed array
  395.  
  396.   if( dwStyle==0 )
  397.     dwStyle = CBS_DROPDOWNLIST;
  398.   toolCtrl[cntToolCtrls].hwnd = CreateWindow ( TEXT( "COMBOBOX" ), TEXT( "" ),
  399.                                   WS_CHILD | // WS_CLIPSIBLINGS |
  400.                                   WS_VISIBLE | dwStyle,
  401.                                   0, 0, 0, 0,
  402.                                   hwndTools, (HMENU) iId, hInstance, NULL );
  403.  
  404.   if( !toolCtrl[cntToolCtrls].hwnd )
  405.     return( (HWND) 0 ); // CreateWindow failed for some reason
  406.  
  407.   // SendMessage (toolCtrl[cntToolCtrls].hwnd, WM_SETFONT, (UINT)hfontTools, MAKELONG (TRUE, 0));
  408.   toolCtrl[cntToolCtrls].wType = TC_COMBO;
  409.  
  410.   if( iWidth < 0 ) {
  411.     toolCtrl[cntToolCtrls].iWidth = tmToolFont.tmAveCharWidth * abs(iWidth);
  412.   }
  413.   else if( iWidth == 0 ) {
  414.     toolCtrl[cntToolCtrls].iWidth = tmToolFont.tmAveCharWidth * 15; // just a default width
  415.   }
  416.   else {
  417.     toolCtrl[cntToolCtrls].iWidth = iWidth;
  418.   }
  419.  
  420.   toolCtrl[cntToolCtrls].iHeight = dyCombo;
  421.   if( (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder)) > dyTools ) {
  422.     dyTools = (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder));
  423.   }
  424.   UpdatePositions( NULL );
  425.  
  426.   return( toolCtrl[cntToolCtrls++].hwnd );
  427. }
  428.  
  429. // ************************************************************************
  430. // FUNCTION : AddToolButton( HANDLE hInst, INT iId, LPTSTR szLabel, INT iWidth, INT iHeight, DWORD dwStyle )
  431. // PURPOSE  :
  432. // COMMENTS :
  433. // ************************************************************************
  434. HWND
  435. AddToolButton( HANDLE hInstance, INT iId, LPTSTR szLabel, INT iWidth, INT iHeight, DWORD dwStyle )
  436. {
  437.   HDC hdc;
  438.  
  439.   if( cntToolCtrls >= MAXCTRLS )
  440.     return( (HWND) 0 ); // No room left in our fixed array
  441.  
  442.   if( dwStyle == 0 )
  443.     dwStyle = BS_PUSHBUTTON | BS_OWNERDRAW;
  444.   toolCtrl[cntToolCtrls].hwnd = CreateWindow ( TEXT( "BUTTON" ), szLabel,
  445.                                   WS_CHILD | // WS_CLIPSIBLINGS |
  446.                                   WS_VISIBLE | dwStyle,
  447.                                   0, 0, 0, 0,
  448.                                   hwndTools, (HMENU)iId, hInstance, NULL );
  449.  
  450.   if( !toolCtrl[cntToolCtrls].hwnd )
  451.     return( (HWND) 0 ); // CreateWindow failed for some reason
  452.  
  453.   // SendMessage (toolCtrl[cntToolCtrls].hwnd, WM_SETFONT, (UINT)hfontTools, MAKELONG (TRUE, 0));
  454.   toolCtrl[cntToolCtrls].wType = TC_BUTTON;
  455.  
  456.   hdc = GetDC (hwndTools);
  457.   SelectObject (hdc, hfontTools);
  458.   if( iWidth < 0 ) {
  459.     toolCtrl[cntToolCtrls].iWidth = tmToolFont.tmAveCharWidth * abs(iWidth);
  460.     toolCtrl[cntToolCtrls].iWidth += (6*cxToolBorder);
  461.   }
  462.   else if( iWidth == 0 ) {
  463.  #ifdef WIN32
  464.     SIZE size;
  465.     GetTextExtentPoint (hdc, szLabel, lstrlen(szLabel), &size);
  466.     toolCtrl[cntToolCtrls].iWidth = size.cx;
  467.  #else
  468.     toolCtrl[cntToolCtrls].iWidth = LOWORD(GetTextExtent (hdc, szLabel, lstrlen(szLabel)));
  469.  #endif
  470.     toolCtrl[cntToolCtrls].iWidth += (6*cxToolBorder);
  471.   }
  472.   else {
  473.     toolCtrl[cntToolCtrls].iWidth = iWidth;
  474.   }
  475.   if( iHeight < 0 ) {
  476.     toolCtrl[cntToolCtrls].iHeight = tmToolFont.tmHeight;
  477.     toolCtrl[cntToolCtrls].iHeight += (6*cyToolBorder);
  478.   }
  479.   else if( iHeight==0 ) {
  480.     toolCtrl[cntToolCtrls].iHeight = dyTools - (6*cyToolBorder);
  481.   } else {
  482.     toolCtrl[cntToolCtrls].iHeight = iHeight;
  483.   }
  484.   if( (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder)) > dyTools ) {
  485.     dyTools = (toolCtrl[cntToolCtrls].iHeight + (6*cyToolBorder));
  486.   }
  487.   if( dwStyle & BS_OWNERDRAW ) {
  488.     toolCtrl[cntToolCtrls].hIcon = LoadIcon (hInstance, szLabel);
  489.   }
  490.   else {
  491.     toolCtrl[cntToolCtrls].hIcon = NULL;
  492.   }
  493.  
  494.   ReleaseDC( hwndTools, hdc );
  495.   UpdatePositions( NULL );
  496.   return toolCtrl[cntToolCtrls++].hwnd;
  497. }
  498.  
  499. // ************************************************************************
  500. // FUNCTION : DestroyToolBar (VOID)
  501. // PURPOSE  :
  502. // COMMENTS :
  503. // ************************************************************************
  504. BOOL
  505. DestroyToolBar( VOID )
  506. {
  507.   return( DeleteObject(hbrBtnFace) );
  508. }
  509.  
  510.  
  511. // ************************************************************************
  512. // FUNCTION : DrawButton (HDC hdc, RECT rect, BOOL bDown, HICON hIcon)
  513. // PURPOSE  :
  514. // COMMENTS :
  515. // ************************************************************************
  516. VOID
  517. DrawButton (HDC hdc, RECT rect, BOOL bDown, HICON hIcon)
  518. {
  519.   HBRUSH  hBrush, hbrFrame, hbrBtnFace, hbrHilite, hbrShadow;
  520.   RECT    border;
  521.   INT     i;
  522.  
  523.   hbrFrame   = CreateSolidBrush( rgbFrame );
  524.   hbrBtnFace = CreateSolidBrush( rgbBtnFace );
  525.   hbrHilite  = CreateSolidBrush( rgbHilite );
  526.   hbrShadow  = CreateSolidBrush( rgbShadow );
  527.  
  528.   FillRect (hdc, &rect, hbrBtnFace);
  529.  
  530.   if( hIcon ) {
  531.     if( bDown ) {
  532.       DrawIcon (hdc, rect.left + (4*cyToolBorder), rect.top + (4*cyToolBorder), hIcon);
  533.     }
  534.     else {
  535.       DrawIcon (hdc, rect.left + (3*cyToolBorder), rect.top + (3*cyToolBorder), hIcon);
  536.     }
  537.   }
  538.  
  539.   hBrush = hbrFrame;
  540.   border = rect; border.bottom = border.top + cyToolBorder;
  541.   FillRect( hdc, &border, hBrush );
  542.   border = rect; border.right = border.left + cxToolBorder;
  543.   FillRect( hdc, &border, hBrush );
  544.   border = rect; border.top = border.bottom - cyToolBorder;
  545.   FillRect( hdc, &border, hBrush );
  546.   border = rect; border.left = border.right - cxToolBorder;
  547.   FillRect( hdc, &border, hBrush );
  548.  
  549.   for( i= 0; i<2; i++ ) {
  550.     InflateRect( &rect, -cxToolBorder, -cyToolBorder );
  551.     hBrush = ( bDown? hbrShadow:hbrHilite );
  552.     border = rect; border.bottom = border.top + cyToolBorder;
  553.     FillRect( hdc, &border, hBrush );
  554.     border = rect; border.right = border.left + cxToolBorder;
  555.     FillRect( hdc, &border, hBrush );
  556.     if( !bDown ) {
  557.       hBrush = hbrShadow;
  558.       border = rect; border.top = border.bottom - cyToolBorder;
  559.       FillRect( hdc, &border, hBrush );
  560.       border = rect; border.left = border.right - cxToolBorder;
  561.       FillRect( hdc, &border, hBrush );
  562.     }
  563.   }
  564.   DeleteObject( hbrFrame );
  565.   DeleteObject( hbrBtnFace );
  566.   DeleteObject( hbrHilite );
  567.   DeleteObject( hbrShadow );
  568.  
  569. }
  570.  
  571.  
  572. // ************************************************************************
  573. // FUNCTION : ToolsProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
  574. // PURPOSE  :
  575. // COMMENTS :
  576. // ************************************************************************
  577. LONG CALLBACK
  578. ToolsProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  579. {
  580.   HDC              hdc;
  581.   PAINTSTRUCT      ps;
  582.   INT              iType, idCtrl, msgCtrl, i;
  583.   RECT             rect, border;
  584.   COLORREF         clrColor = rgbToolBar;
  585.   HWND             hwndCtl;
  586.   LONG             lStyle;
  587.   HBRUSH           hBrush = hbrToolBar;
  588.   LPDRAWITEMSTRUCT lpdi;
  589.   HICON            hIcon;
  590.  
  591.   switch( msg ) {
  592.  
  593.     case WM_CREATE:
  594.       //DebugOut( "[ToolsProc] WM_CREATE" );
  595.  
  596.      #ifdef NOCREATEFONT // CreateFont is failing in NT
  597.       hfontTools = (HFONT)NULL;
  598.      #else
  599.       hfontTools = CreateFont(16, 0, 0, 0, 0, 0, 0, 0,
  600.                       ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  601.                       DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, NULL);
  602.       if( !hfontTools ) {
  603.         MessageBox( GetFocus(), TEXT( "Failed To Create Font" ),
  604.           TEXT( "StatusProc" ), MB_OK );
  605.       }
  606.      #endif
  607.        hdc = GetDC( hwnd );
  608.        SelectObject( hdc, hfontTools );
  609.        GetTextMetrics( hdc, &tmToolFont );
  610.        ReleaseDC( hwnd, hdc );
  611.       //DebugOut( "[ToolsProc] WM_CREATE (exit)" );
  612.        return( DefWindowProc( hwnd, msg, wParam, lParam ) );
  613.  
  614.     case WM_SIZE:
  615.       UpdatePositions(hwnd);
  616.       break;
  617.  
  618.    #ifdef WIN32
  619.     case WM_CTLCOLORLISTBOX:
  620.     case WM_CTLCOLOREDIT:
  621.     case WM_CTLCOLORSTATIC:
  622.     case WM_CTLCOLORBTN:
  623.     case WM_CTLCOLORDLG:
  624.     case WM_CTLCOLORMSGBOX:
  625.     case WM_CTLCOLORSCROLLBAR:
  626.       iType   = msg - WM_CTLCOLORMSGBOX;
  627.       hdc     = (HDC)wParam;
  628.       hwndCtl = (HWND)lParam;
  629.    #else
  630.     case WM_CTLCOLOR:
  631.       hdc = wParam;
  632.       hwndCtl = LOWORD( lParam );
  633.       iType = HIWORD ( lParam );
  634.    #endif
  635.  
  636.       switch (iType) {
  637.         case CTLCOLOR_EDIT: //Edit control
  638.           clrColor = rgbBtnFace;
  639.           hBrush = hbrToolBar;
  640.           break;
  641.  
  642.         case CTLCOLOR_LISTBOX: //List-box control
  643.           lStyle = GetWindowLong (hwndCtl, GWL_STYLE);
  644.           if( lStyle & CBS_SIMPLE ) {
  645.             clrColor = rgbToolBar;
  646.             hBrush = hbrToolBar;
  647.           }
  648.           else {
  649.             clrColor = rgbBtnFace;
  650.             hBrush = hbrToolBar;
  651.           }
  652.           break;
  653.  
  654.         case CTLCOLOR_STATIC:
  655.           clrColor = rgbBtnFace;
  656.           hBrush = hbrBtnFace;
  657.           break;
  658.  
  659.         case CTLCOLOR_BTN:
  660.           clrColor = rgbBtnFace;
  661.           hBrush = hbrBtnFace;
  662.           break;
  663.  
  664.         case CTLCOLOR_SCROLLBAR:
  665.         case CTLCOLOR_DLG:
  666.         case CTLCOLOR_MSGBOX:
  667.         default:
  668.           return FALSE;
  669.       }
  670.       SetBkColor(hdc, clrColor);
  671.       return (LONG)hBrush;
  672.  
  673.     case WM_PAINT:
  674.       hdc = BeginPaint (hwnd, &ps);
  675.       GetClientRect (hwnd, &rect);
  676.       /* Shade the top of the bar white */
  677.       hBrush = CreateSolidBrush( rgbDirectLight );
  678.       border = rect;
  679.       border.bottom = border.top + cyToolBorder;
  680.       FillRect (hdc, &border, hBrush);
  681.       DeleteObject (hBrush);
  682.       /* Shade the bottom of the bar dark gray */
  683.       hBrush = CreateSolidBrush( rgbShadow );
  684.       border = rect;
  685.       border.top = border.bottom - cyToolBorder;
  686.       FillRect (hdc, &border, hBrush);
  687.       DeleteObject (hBrush);
  688.       EndPaint (hwnd, &ps);
  689.       return DefWindowProc (hwnd, msg, wParam, lParam);
  690.  
  691.     case WM_DRAWITEM: // Indicates that an owner-draw control needs to be redrawn.
  692.       lpdi = (LPDRAWITEMSTRUCT)lParam;
  693.       switch( lpdi->itemAction ) {
  694.         // handle normal drawing of button, but check if its selected or focus
  695.         case ODA_SELECT:
  696.         case ODA_DRAWENTIRE:
  697.           // handle button pressed down select state -- button down bitmap
  698.           //   text is right & down 2 pixels
  699.           hIcon = NULL;
  700.           for( i=0; i< cntToolCtrls; i++ ) {
  701.             if( toolCtrl[i].hwnd == lpdi->hwndItem ) {
  702.               hIcon = toolCtrl[i].hIcon;
  703.             }
  704.           }
  705.           if( lpdi->itemState & ODS_SELECTED ) {
  706.             DrawButton( lpdi->hDC,lpdi->rcItem, TRUE, hIcon );
  707.           }
  708.           else { // not selected -- button up; text is in normal position
  709.             DrawButton( lpdi->hDC,lpdi->rcItem, FALSE, hIcon );
  710.           }
  711.           return( TRUE );
  712.       }
  713.       break;
  714.  
  715.     case WM_COMMAND:
  716.      #ifdef WIN32
  717.       idCtrl  = LOWORD( wParam );
  718.       msgCtrl = HIWORD( wParam );
  719.       hwndCtl = (HWND) lParam;
  720.      #else
  721.       idCtrl  = wParam;
  722.       msgCtrl = HIWORD( lParam );
  723.       hwndCtl = LOWORD( lParam );
  724.      #endif
  725.       if( GetWindowLong( hwndCtl, GWL_STYLE ) & BS_OWNERDRAW ) {
  726.         if( msgCtrl == BN_DOUBLECLICKED ) {
  727.           PostMessage( hwndCtl, WM_LBUTTONDOWN, 0, 0 );
  728.           return( TRUE );
  729.         }
  730.       }
  731.       PostMessage (hwndMain, msg, wParam, lParam);
  732.       return DefWindowProc (hwnd, msg, wParam, lParam);
  733.  
  734.  
  735.     default:
  736.       return( DefWindowProc( hwnd, msg, wParam, lParam ) );
  737.   }
  738.   return( 0L );
  739. }
  740.  
  741.  
  742. // ========================================================================
  743. //                        STATUS BAR FUNCTIONS
  744. // ========================================================================
  745.  
  746.  
  747. // ************************************************************************
  748. // FUNCTION :
  749. // PURPOSE  :
  750. // COMMENTS :
  751. // ************************************************************************
  752. BOOL
  753. InitStatusBar( HANDLE hInstance )
  754. {
  755.   WNDCLASS    wndclass;
  756.  
  757.   hbrStatus = CreateSolidBrush( rgbBtnFace );
  758.  
  759.   wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  760.   wndclass.lpfnWndProc   = (WNDPROC)StatusProc;
  761.   wndclass.cbClsExtra    = 0;
  762.   wndclass.cbWndExtra    = 0;
  763.   wndclass.hInstance     = hInstance;
  764.   wndclass.hIcon         = NULL;
  765.   wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
  766.   wndclass.hbrBackground = hbrStatus;
  767.   wndclass.lpszMenuName  = NULL;
  768.   wndclass.lpszClassName = TEXT( "SamplerStatus" );
  769.  
  770.   if( !RegisterClass(&wndclass) )
  771.     return( FALSE );
  772.  
  773.   wndclass.style         = CS_HREDRAW | CS_VREDRAW;
  774.   wndclass.lpfnWndProc   = (WNDPROC)StatusFieldProc;
  775.   wndclass.cbClsExtra    = 0;
  776.   wndclass.cbWndExtra    = 0;
  777.   wndclass.hInstance     = hInstance;
  778.   wndclass.hIcon         = NULL;
  779.   wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
  780.   wndclass.hbrBackground = hbrStatus;
  781.   wndclass.lpszMenuName  = NULL;
  782.   wndclass.lpszClassName = TEXT( "StatusField" );
  783.  
  784.   if( !RegisterClass (&wndclass) )
  785.     return( FALSE );
  786.  
  787. }
  788.  
  789. // ************************************************************************
  790. // FUNCTION :
  791. // PURPOSE  :
  792. // COMMENTS :
  793. // ************************************************************************
  794. BOOL
  795. CreateStatusBar (HWND hwnd, HANDLE hInstance, INT iId)
  796. {
  797.   cxStatusBorder = GetSystemMetrics (SM_CXBORDER);
  798.   cyStatusBorder = GetSystemMetrics (SM_CYBORDER);
  799.  
  800.   //DebugOut( ": Calling CreateWindow" );
  801.   hwndStatus = CreateWindow ( TEXT( "SamplerStatus" ), TEXT( "SamplerStatus" ),
  802.     WS_CHILD //| WS_CLIPSIBLINGS
  803.     | WS_BORDER | WS_VISIBLE,
  804.     0, 0, 0, 0,
  805.     hwnd, (HMENU)iId, hInstance, NULL);
  806.  
  807.   if (!hwndStatus) {
  808.           return FALSE;
  809.   }
  810.   //DebugOut( "CreateWindow Succeeded" );
  811.   return TRUE;
  812. }
  813.  
  814. // ************************************************************************
  815. // FUNCTION :
  816. // PURPOSE  :
  817. // COMMENTS :
  818. // ************************************************************************
  819. int
  820. StatusBarHeight (HWND hwnd)
  821. {
  822.   RECT rect;
  823.  
  824.   GetClientRect( hwndStatus, &rect );
  825.  
  826.   return rect.bottom-rect.top;
  827.  
  828.   hwnd; // unreferenced
  829. }
  830.  
  831. // ************************************************************************
  832. // FUNCTION :
  833. // PURPOSE  :
  834. // COMMENTS :
  835. // ************************************************************************
  836. BOOL
  837. AdjustStatusBar (HWND hwnd)
  838. {
  839.   RECT rect;
  840.   GetClientRect (hwnd, &rect);
  841.   MoveWindow (hwndStatus,
  842.     rect.left-cxStatusBorder,
  843.     rect.bottom - dyStatus + cyStatusBorder,
  844.     rect.right - rect.left + (cxStatusBorder*2),
  845.     dyStatus, TRUE);
  846.   return TRUE;
  847. }
  848.  
  849. // ************************************************************************
  850. // FUNCTION :
  851. // PURPOSE  :
  852. // COMMENTS :
  853. // ************************************************************************
  854. HWND
  855. AddStatusField (HANDLE hInstance, INT iId, INT iMin, INT iMax, BOOL bNewGroup)
  856. {
  857.   LONG lStyle;
  858.  
  859.   if( cntStatusField >= MAXSTATUS )
  860.     return( (HWND) 0 ); // No room left in our fixed array
  861.   statusField[cntStatusField].hwnd = CreateWindow( TEXT( "StatusField" ), TEXT( "" ),
  862.                                        WS_CHILD | WS_VISIBLE,
  863.                                        0, 0, 0, 0,
  864.                                        hwndStatus, (HMENU)iId,
  865.                                        hInstance, NULL );
  866.   if( !statusField[cntStatusField].hwnd )
  867.     return( (HWND) 0 ); // CreateWindow failed for some reason
  868.   if( iMin < 0 ) {
  869.     statusField[cntStatusField].iMinWidth = tmStatusFont.tmAveCharWidth*abs(iMin);
  870.   }
  871.   else {
  872.     statusField[cntStatusField].iMinWidth = iMin;
  873.   }
  874.   if( iMax < 0 ) {
  875.     statusField[cntStatusField].iMaxWidth = tmStatusFont.tmAveCharWidth*abs(iMax);
  876.   }
  877.   else {
  878.     statusField[cntStatusField].iMaxWidth = iMax;
  879.   }
  880.   if( bNewGroup ) {
  881.     lStyle = GetWindowLong( statusField[cntStatusField].hwnd, GWL_STYLE );
  882.     lStyle |= WS_GROUP;
  883.     SetWindowLong( statusField[cntStatusField].hwnd, GWL_STYLE, lStyle );
  884.   }
  885.  
  886.   return( statusField[cntStatusField++].hwnd );
  887. }
  888.  
  889. // ************************************************************************
  890. // FUNCTION :
  891. // PURPOSE  :
  892. // COMMENTS :
  893. // ************************************************************************
  894. BOOL
  895. DestroyStatusBar (VOID)
  896. {
  897.   return( DeleteObject( hbrStatus ) );
  898. }
  899.  
  900. // ************************************************************************
  901. // FUNCTION :
  902. // PURPOSE  :
  903. // COMMENTS :
  904. // ************************************************************************
  905. LONG CALLBACK
  906. StatusProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  907. {
  908.   HDC         hdc;
  909.   PAINTSTRUCT ps;
  910.   INT         x, y, i;
  911.   INT         wAvailWidth, wFlexWidth, cntFlexWidth, wNeedWidth, cntNeedWidth;
  912.   RECT        rect, border;
  913.   HBRUSH      hBrush;
  914.  
  915.   switch (msg) {
  916.     case WM_CREATE:
  917.      #ifdef NOCREATEFONT // CreateFont is failing in NT
  918.       hfontStatus = (HFONT)NULL;
  919.      #else
  920.       hfontStatus = CreateFont(16, 0, 0, 0, 0, 0, 0, 0,
  921.               ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  922.               DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, NULL);
  923.       if( !hfontStatus ) {
  924.         MessageBox( GetFocus(), TEXT( "Failed To Create Font" ),
  925.           TEXT( "StatusProc" ), MB_OK );
  926.       }
  927.      #endif
  928.       hdc = GetDC (hwnd);
  929.       SelectObject (hdc, hfontStatus);
  930.       GetTextMetrics (hdc, &tmStatusFont);
  931.       cxStatusBorder = GetSystemMetrics (SM_CXBORDER);
  932.       cyStatusBorder = GetSystemMetrics (SM_CYBORDER);
  933.       cxFrame = 3*cxStatusBorder;
  934.       cyFrame = 3*cyStatusBorder;
  935.       dyField = tmStatusFont.tmHeight + (2*cyStatusBorder);
  936.       dyStatus = dyField + (2*cyFrame);
  937.       ReleaseDC (hwnd, hdc);
  938.       return DefWindowProc (hwnd, msg, wParam, lParam);
  939.  
  940.     case WM_SIZE:
  941.       if( cntStatusField ) {
  942.         GetClientRect (hwnd, &rect);
  943.         wAvailWidth = rect.right - rect.left - (cxStatusBorder*8);
  944.         wNeedWidth = 0;
  945.         cntNeedWidth = 0;
  946.         cntFlexWidth = 0;
  947.  
  948.         /* First Pass: Dole out to fields that have a minimum need */
  949.         for (i=0; i<cntStatusField; i++) {
  950.           statusField[i].iGiveWidth = 0; // Make sure all are initialized to 0
  951.           if( statusField[i].iMinWidth ) {
  952.             /* (n, ?) */
  953.             statusField[i].iGiveWidth = statusField[i].iMinWidth;
  954.             wAvailWidth -= (statusField[i].iGiveWidth + cxStatusBorder*2);
  955.             if( GetWindowLong(statusField[i].hwnd, GWL_STYLE) & WS_GROUP ) {
  956.               wAvailWidth -= cxStatusBorder*4;
  957.             }
  958.           }
  959.           else {
  960.             /* They didn't specify a minimum... don't give them anything yet */
  961.             /* (0, ?) */
  962.             statusField[i].iGiveWidth = 0;
  963.             //++cntFlexWidth;
  964.           }
  965.           /* For those that have a minimum, but can grow to be as large as possible...*/
  966.           /* (n, 0) */
  967.           if( (statusField[i].iMinWidth >0) && (statusField[i].iMaxWidth ==0) ) {
  968.             ++cntFlexWidth;
  969.           }
  970.           /* For those that have a max that is greater then their min... */
  971.           /* Includes (0,n) and (n,>n) */
  972.           if( statusField[i].iMaxWidth > statusField[i].iGiveWidth ) {
  973.             wNeedWidth += (statusField[i].iMaxWidth - statusField[i].iGiveWidth);
  974.             ++cntNeedWidth;
  975.           }
  976.         }
  977.  
  978.         /* Second Pass: Dole out to fields that have a stated maximum need */
  979.         /* This will also hit those who had no minimum, but did have a maximum */
  980.         /* It will still not give anything to those with no min, no max */
  981.         if( (cntNeedWidth > 0) && (wAvailWidth > 0) ) {
  982.           if( wNeedWidth > wAvailWidth ) {
  983.             wNeedWidth = wAvailWidth;
  984.           }
  985.           wNeedWidth = wNeedWidth / cntNeedWidth;
  986.           for( i=0; i<cntStatusField; i++ ) {
  987.             if( statusField[i].iMaxWidth > statusField[i].iGiveWidth ) {
  988.               statusField[i].iGiveWidth += wNeedWidth;
  989.               wAvailWidth -= (statusField[i].iGiveWidth + cxStatusBorder*2);
  990.               if( GetWindowLong(statusField[i].hwnd, GWL_STYLE) & WS_GROUP ) {
  991.                 wAvailWidth -= cxStatusBorder*4;
  992.               }
  993.             }
  994.           }
  995.         }
  996.  
  997.         /* Third Pass: Dole out the remaining to fields that want all they can get */
  998.         /* This includes those who had a minimum, but no maximum */
  999.         if( (cntFlexWidth > 0) && (wAvailWidth > 0) ) {
  1000.           wFlexWidth = wAvailWidth / cntFlexWidth;
  1001.           for( i=0; i<cntStatusField; i++ ) {
  1002.             if( statusField[i].iMaxWidth==0 ) {
  1003.               statusField[i].iGiveWidth += wFlexWidth;
  1004.               wAvailWidth -= ((wFlexWidth - statusField[i].iMinWidth) + cxStatusBorder*2);
  1005.               if( GetWindowLong(statusField[i].hwnd, GWL_STYLE) & WS_GROUP ) {
  1006.                wAvailWidth -= cxStatusBorder*4;
  1007.               }
  1008.             }
  1009.           }
  1010.         }
  1011.  
  1012.         x = cxStatusBorder*4;
  1013.         y = rect.top + (2*cyStatusBorder);
  1014.         for( i=0; i<cntStatusField; i++ ) {
  1015.           if( GetWindowLong (statusField[i].hwnd, GWL_STYLE) & WS_GROUP ) {
  1016.             x += (cxStatusBorder*4);
  1017.           }
  1018.           MoveWindow( statusField[i].hwnd, x, y, statusField[i].iGiveWidth, dyField, TRUE );
  1019.           x += statusField[i].iGiveWidth + (cxStatusBorder*2);
  1020.         }
  1021.       }
  1022.       break;
  1023.  
  1024.     case WM_PAINT:
  1025.       hdc = BeginPaint( hwnd, &ps );
  1026.       GetClientRect( hwnd, &rect );
  1027.       hBrush = CreateSolidBrush( rgbToolBar );
  1028.       border = rect;
  1029.       border.bottom = border.top + cyStatusBorder;
  1030.       FillRect( hdc, &border, hBrush );
  1031.       DeleteObject (hBrush);
  1032.       hBrush = CreateSolidBrush( rgbShadow );
  1033.       border = rect;
  1034.       border.top = border.bottom - cyStatusBorder;
  1035.       FillRect( hdc, &border, hBrush );
  1036.       DeleteObject( hBrush );
  1037.       EndPaint( hwnd, &ps );
  1038.       return( DefWindowProc (hwnd, msg, wParam, lParam) );
  1039.  
  1040.     default:
  1041.       return( DefWindowProc( hwnd, msg, wParam, lParam ) );
  1042.  
  1043.   }
  1044.  
  1045.   return( 0L );
  1046. }
  1047.  
  1048.  
  1049. // ************************************************************************
  1050. // FUNCTION :
  1051. // PURPOSE  :
  1052. // COMMENTS :
  1053. // ************************************************************************
  1054. LONG CALLBACK
  1055. StatusFieldProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1056. {
  1057.   static HFONT hFieldFont;
  1058.  
  1059.   HDC         hdc;
  1060.   PAINTSTRUCT ps;
  1061.   RECT        rect, border;
  1062.   HBRUSH      hBrush;
  1063.   WORD        edge = 1;
  1064.   HFONT       hTmp;
  1065.   TCHAR       szText[80];
  1066.   INT         len;
  1067.  
  1068.   switch( msg ) {
  1069.     case WM_CREATE:
  1070.       hFieldFont = CreateFont( 8, 0, 0, 0, 0, 0, 0, 0,
  1071.                      ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  1072.                      DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, TEXT( "Helv" ) );
  1073.       return( DefWindowProc( hwnd, msg, wParam, lParam ) );
  1074.  
  1075.     case WM_PAINT:
  1076.       hdc = BeginPaint( hwnd, &ps );
  1077.       GetClientRect( hwnd, &rect );
  1078.       //-- fill top of the status windows
  1079.       hBrush = CreateSolidBrush( rgbShadow );
  1080.       border = rect;
  1081.       border.bottom = border.top + cyStatusBorder;
  1082.       FillRect( hdc, &border, hBrush );
  1083.       border = rect;
  1084.       border.right = border.left + cxStatusBorder;
  1085.       FillRect( hdc, &border, hBrush );
  1086.       DeleteObject( hBrush );
  1087.       //-- fill botton of the status windows
  1088.       hBrush = CreateSolidBrush( rgbDirectLight );
  1089.       border = rect;
  1090.       border.top = border.bottom - cyStatusBorder;
  1091.       FillRect( hdc, &border, hBrush );
  1092.       border = rect;
  1093.       border.left = border.right - cxStatusBorder;
  1094.       FillRect( hdc, &border, hBrush );
  1095.       DeleteObject( hBrush );
  1096.  
  1097.       if( len = GetWindowText( hwnd, szText, sizeof (szText) ) ) {
  1098.         hTmp = SelectObject( hdc, hfontStatus );
  1099.         SetTextColor( hdc, rgbStatic );
  1100.         SetBkColor( hdc, rgbToolBar );
  1101.         InflateRect( &rect, -(cxStatusBorder*2), -cyStatusBorder );
  1102.         ExtTextOut( hdc, rect.left, rect.top,
  1103.           ETO_OPAQUE | ETO_CLIPPED,
  1104.           &rect,
  1105.           (LPTSTR) szText,
  1106.           len, NULL);
  1107.         SelectObject( hdc, hTmp );
  1108.       }
  1109.       EndPaint( hwnd, &ps );
  1110.       break;
  1111.  
  1112.     case WM_SETTEXT:
  1113.       InvalidateRect( hwnd, NULL, TRUE );
  1114.       return( DefWindowProc( hwnd, msg, wParam, lParam ) );
  1115.  
  1116.     default:
  1117.       return( DefWindowProc( hwnd, msg, wParam, lParam ) );
  1118.   }
  1119.  
  1120.   return( 0L );
  1121. }
  1122.